/*
 * @Author: yangzonglong
 * @Date: 2021-03-01 13:18:46
 * @version: v1.0.0
 * @Descripttion:
 * @LastEditors: yangzonglong
 * @LastEditTime: 2023-10-08 14:52:42
 * @Auditor:
 */
import React, { useCallback, useState, useImperativeHandle, forwardRef, useEffect, useRef } from 'react';
import { Form, Select, Input } from 'antd';
import Icon from '../icon/Icon';
import { getModalOptions, getExtraObjByFiledShowName } from '../../util';
import ModalTableInModel from '@library/components/modalTableInModel/ModalTableInModel';
import useQueryControlWrap from '../../hooks/useQueryControlWrap';
import { CanvasItemProps } from '../../interface';
import { FormItemProps } from '../components/InputFormItemController';
import { message } from '@library/utils';

export interface DataLinkItemProps extends CanvasItemProps {
  formItemProps?: FormItemProps;
  inputProps: any;
  disabled?: boolean;
  initialValue?: any;
  sendData?: any;
  scriptsChangeData?: Object;
  onValuesChange?(name: string, data: any): void;
}

interface RefProps {
  getData(): any;
}

const copyToClipboard = (value: string) => {
  const textarea = document.createElement('textarea');
  textarea.value = value;
  document.body.appendChild(textarea);
  textarea.select();
  document.execCommand('copy');
  document.body.removeChild(textarea);
  message.success('复制成功');
};

const getNames = (showFieldName: string | string[], next: any) => {
  if (typeof showFieldName === 'string') {
    return next?.[showFieldName] || '';
  } else {
    let str = showFieldName.reduce((all: string, now: any, index: number) => {
      return all + (next[now.value] || '') + (index === showFieldName.length - 1 || !next[now.value] ? '' : '-');
    }, '');
    return str;
  }
};

const App = (props: DataLinkItemProps, ref: React.Ref<RefProps>) => {
  const { initialValue, disabled, formItemProps, domComplete, inputProps, scriptsChangeData, controlRefs, getCurrInterceptors, ...canvasProps } = props;

  const [showFormItem, setShowFormItem] = useState(true);
  const count = useRef(0);
  const doubleClickRef = useRef<any>(null);
  const cacheData = useRef(scriptsChangeData![inputProps?.bindName]);

  useEffect(() => {
    if (initialValue && Array.isArray(initialValue)) {
      setRows(initialValue);
      setValue(initialValue.reduce((all: string, next: object) => { return (all + ' ') + (getNames(inputProps.showFieldName, next) || ''); }, ''));
    } else if (initialValue && typeof initialValue === 'object') {
      setRows([initialValue]);
      setValue([initialValue].reduce((all: string, next: object) => { return (all + ' ') + (getNames(inputProps.showFieldName, next) || ''); }, ''));
    }
  }, [initialValue, inputProps.showFieldName]);

  useEffect(() => {
    if (count.current === 0) {
      count.current = 1;
    } else {
      if (JSON.stringify(cacheData.current) !== JSON.stringify(scriptsChangeData![inputProps?.bindName])) {
        cacheData.current = scriptsChangeData![inputProps?.bindName];
        setRows([]);
        setValue(undefined);
        props.onValuesChange?.(props.formItemProps!.name as string, undefined);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [scriptsChangeData![inputProps?.bindName]]);

  const [visible, setVisible] = useState(false);
  const [hideIcon, setHideIcon] = useState(false);
  const [value, setValue] = useState<any>(undefined);
  const [rows, setRows] = useState<any[]>([]);
  const [model, setModel] = useState<any>({ columns: [] });


  useQueryControlWrap(canvasProps.id, formItemProps?.name, domComplete);

  const onShow = useCallback(() => {
    setVisible(true);
    const model = getModalOptions(formItemProps!, inputProps, scriptsChangeData!, getCurrInterceptors);
    setModel(model);;
  }, [formItemProps, inputProps, scriptsChangeData, getCurrInterceptors]);

  const onOk = useCallback(
    (rows: object[], onChange: (v: any) => void) => {

      const mapFileds = inputProps.mapFileds || {};

      const [_rows, outward] = getExtraObjByFiledShowName(rows, ((inputProps?.filedShowName || []).concat(
        inputProps?.extraFieldName || []
      )), mapFileds);

      setRows(_rows as any[]);
      setValue(rows.reduce((all: string, next: object) => { return (all + ' ') + (getNames(inputProps.showFieldName, next) || ''); }, ''));
      setVisible(false);
      onChange(rows);

      for (let k in outward) {
        controlRefs?.[k]?.setData?.(outward[k]);
      }
    },
    [inputProps, controlRefs]
  );

  const onHide = useCallback(() => setVisible(false), []);

  useImperativeHandle(ref, () => ({
    getData() {
      return rows.length === 1 && !formItemProps?.radio ? rows[0] : (formItemProps?.radio ? rows : (rows?.[0] || {}));
    },
    setData(initialValue: any) {
      if (initialValue && Array.isArray(initialValue)) {
        setRows(initialValue);
        setValue(initialValue.reduce((all: string, next: object) => { return (all + ' ') + (getNames(inputProps.showFieldName, next) || ''); }, ''));
      } else if (initialValue && typeof initialValue === 'object') {
        setRows([initialValue]);
        setValue([initialValue].reduce((all: string, next: object) => { return (all + ' ') + (getNames(inputProps.showFieldName, next) || ''); }, ''));
      } else if (initialValue === null) {
        setValue(null);
        setRows([]);
      }
    },
    hideFormItem() {
      setShowFormItem(false);
    },
    showModal() {
      onShow();
    }
  }));

  function handleResult(result: { count: number; rows: any[]; }) {
    result?.rows?.forEach((item, index) => {
      if (!item.id) item.id = 'MOCK_' + index;
    });

    const currInterceptors = getCurrInterceptors?.(model.url);

    if (currInterceptors?.get) return currInterceptors.get(result);

    return result;
  }

  const CombineNode = (props: any) => {
    const placeholder = localStorage.i18nextLng === 'en' ? inputProps?.placeholderEn : inputProps?.placeholder;

    return (
      <>
        {showFormItem && (disabled || inputProps?.disabled) ? (
          <Input disabled value={value} />
        ) : (
          showFormItem && <Select
            disabled={disabled || inputProps?.disabled}
            onClick={(e: any) => {
              if (doubleClickRef.current) {
                clearTimeout(doubleClickRef.current);
                copyToClipboard(value);
                doubleClickRef.current = null;
                return;
              }
              doubleClickRef.current = setTimeout(() => {
                e && onShow();
                doubleClickRef.current = null;
              }, 200);
            }}
            value={value}
            notFoundContent={null}
            allowClear
            onClear={() => onOk([{}], props.onChange)}
            suffixIcon={<Icon icon="&#xe63b;" style={hideIcon ? { opacity: 0 } : {}} />}
            onMouseEnter={() => value && setHideIcon(true)}
            onMouseLeave={() => setHideIcon(false)}
            placeholder={disabled || inputProps?.disabled ? "" : placeholder}
          ></Select>
        )}
        {
          <ModalTableInModel
            showAutoSearch
            handleQuerySet={model.handleQuerySet}
            defaultSelected={rows}
            showSelected={inputProps?.showFieldName}
            onOk={(data) => onOk(data, props.onChange)}
            hideSearch={false}
            model={model}
            rowSelectionType={formItemProps?.radio ? 'checkbox' : 'radio'}
            onCancel={onHide}
            visible={visible}
            handleResult={handleResult}
            treeStructure={formItemProps?.treeStructure}
            treeId={formItemProps?.treeId}
            treeParentId={formItemProps?.treeParentId}
          />
        }
      </>
    );
  };

  const label = localStorage.i18nextLng === 'en' ? formItemProps?.labelEn : formItemProps?.label;

  return showFormItem ? (
    <Form.Item {...canvasProps} {...formItemProps} label={label}>
      <CombineNode />
    </Form.Item>
  ) : <Form.Item name={formItemProps?.name || canvasProps.id || canvasProps._id}>
    <CombineNode />
  </Form.Item>;
};

export default forwardRef(App);
